﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Graphics.Display;
using Windows.Graphics.Imaging;
using Windows.Storage;
using Windows.Storage.Streams;
using Windows.UI.Core;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
using Windows.UI.Xaml.Navigation;

// https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x804 上介绍了“空白页”项模板

namespace AppCaptureImage
{
    /// <summary>
    /// 可用于自身或导航至 Frame 内部的空白页。
    /// </summary>
    public sealed partial class MainPage : Page
    {
        static readonly StorageFolder LocalStorageFolder = Windows.Storage.ApplicationData.Current.LocalFolder;

        public static readonly string BlobSubPath = $"\\Blobs";
        public static readonly string BlobStoragePath = $"{LocalStorageFolder.Path}{BlobSubPath}";
        public static StorageFolder BlobFolder = null;
        public MainPage()
        {
            this.InitializeComponent();
            if (!Directory.Exists(BlobStoragePath))
            {
                Directory.CreateDirectory(BlobStoragePath);
            }
        }
        private async void Page_Loaded(object sender, RoutedEventArgs e)
        {
            BlobFolder = await LocalStorageFolder.GetFolderAsync("Blobs");

            this.txtAppPath.Text = LocalStorageFolder.Path;
        }
        //RenderTargetBitmap
        // 截一个3s的动画，每s两帧
        private async void Button_Click(object sender, RoutedEventArgs e)
        {
            await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,async () =>
            {
                await CaptureAppToJpg(this);
                await CaptureAppToGif(this);
            });
        }
        /// <summary>
        /// 应用截屏成Gif动态图 (默认3s，每秒2帧)
        /// </summary>
        /// <returns>返回生成的gif图片</returns>
        private async Task<StorageFile> CaptureAppToGif(UIElement containner,int frames = 6, int delay = 500 , uint scaleValue =400)
        {
            StorageFile file = await BlobFolder.CreateFileAsync($"{DateTime.Now.Ticks}.gif", CreationCollisionOption.GenerateUniqueName);
            using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))
            {
                var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.GifEncoderId, stream);
                Dictionary<string, BitmapTypedValue> props = new Dictionary<string, BitmapTypedValue>();
                // 此字段必须
                props.Add("/appext/Application", new BitmapTypedValue(System.Text.Encoding.UTF8.GetBytes("NETSCAPE2.0"), PropertyType.UInt8Array));
                // 表示循环播放
                props.Add("/appext/Data", new BitmapTypedValue(new byte[] { 3, 1, 0, 0 }, PropertyType.UInt8Array));
                // Delay表示每一帧的时间间隔，单位为1/100秒
                props.Add("/grctlext/Delay", new BitmapTypedValue(delay /10, PropertyType.UInt16));
                props.Add("/grctlext/Disposal", new BitmapTypedValue((byte)2, PropertyType.UInt8));

                await encoder.BitmapProperties.SetPropertiesAsync(props); //写入元数据
                for (int i = 0; i < frames; i++)
                {
                    var bitmap = new RenderTargetBitmap();
                    await bitmap.RenderAsync(containner);
                    var buffer = await bitmap.GetPixelsAsync();
                    encoder.SetPixelData(BitmapPixelFormat.Bgra8,
                       BitmapAlphaMode.Ignore,
                       (uint)bitmap.PixelWidth,
                       (uint)bitmap.PixelHeight,
                       DisplayInformation.GetForCurrentView().LogicalDpi,
                       DisplayInformation.GetForCurrentView().LogicalDpi,
                       buffer.ToArray()
                      );
                    //进行缩放
                    uint oriWidth = (uint)bitmap.PixelWidth;
                    uint oriHeight = (uint)bitmap.PixelHeight;
                    uint tarWidth = scaleValue;
                    uint tarHeight = (uint)((float)tarWidth / (float)oriWidth * (float)oriHeight);
                    encoder.BitmapTransform.ScaledWidth = tarWidth;
                    encoder.BitmapTransform.ScaledHeight = tarHeight;
                    if (i < frames - 1)
                        await encoder.GoToNextFrameAsync();
                    await Task.Delay(delay);
                }
                
                await encoder.FlushAsync();
            }
            return file;
        }
        /// <summary>
        /// 应用截屏
        /// </summary>
        /// <param name="containner"></param>
        /// <returns></returns>
        private async Task<StorageFile> CaptureAppToJpg(UIElement containner, uint scaleValue = 400)
        {
            StorageFile file = await BlobFolder.CreateFileAsync($"{DateTime.Now.Ticks}.jpg", CreationCollisionOption.GenerateUniqueName);
            using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))
            {
                var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream);
                
                var bitmap = new RenderTargetBitmap();
                await bitmap.RenderAsync(containner);
                var buffer = await bitmap.GetPixelsAsync();

                encoder.SetPixelData(BitmapPixelFormat.Bgra8,
                   BitmapAlphaMode.Ignore,
                   (uint)bitmap.PixelWidth,
                   (uint)bitmap.PixelHeight,
                   DisplayInformation.GetForCurrentView().LogicalDpi,
                   DisplayInformation.GetForCurrentView().LogicalDpi,
                   buffer.ToArray()
                  );
                // 进行缩放
                uint oriWidth = (uint)bitmap.PixelWidth;
                uint oriHeight = (uint)bitmap.PixelHeight;
                uint tarWidth = scaleValue;
                uint tarHeight = (uint)((float)tarWidth / (float)oriWidth * (float)oriHeight);

                encoder.BitmapTransform.ScaledWidth = tarWidth;
                encoder.BitmapTransform.ScaledHeight = tarHeight;
                await encoder.FlushAsync();
            }
            return file;
        }
    }
}
